#include "Timer.h"
#include "DateTime.h"
#include "Tracer.h"
#include <signal.h>

namespace libemb{
Timer::Timer(const TimerListener& listener,int timerID)
{
    m_listener = const_cast<TimerListener*>(&listener);
}

Timer::~Timer()
{
}

bool Timer::start(int seconds, int repeats)
{
    Time interval(m_interval,0);
    m_alarmTime = Time::fromEpoch()+interval;
    m_interval = seconds;
    m_repeats = repeats;
    m_startFlag = true;
    return true;
}
void Timer::stop()
{
    m_startFlag = false;
}

/* 比较时间 */
void Timer::checkAlarm()
{
    if (!m_startFlag)
    {
        return;
    }

    Time currTime = Time::fromEpoch();
    if (m_alarmTime.secPart()==currTime.secPart() && m_listener!=nullptr)
    {
        m_listener->onTimer(m_timerID);
        if (m_repeats==0)/* 不重复,直接检查是否到时间 */
        {
            stop();	
        }
        else if (m_repeats>0) /* 重复m_repeats次 */
        {
            m_repeats--;
            Time interval(m_interval,0);
            m_alarmTime = m_alarmTime + interval;
        }
        else /* m_repeats<0 : 永远重复 */
        {
            m_repeats = -1;
            Time interval(m_interval,0);
            m_alarmTime = m_alarmTime + interval;
        }
    }

}

TimerManager::TimerManager()
{
    m_thread = std::make_unique<Thread>();
}

TimerManager::~TimerManager()
{
}

bool TimerManager::registerTimer(const Timer& timer)
{
    if (!m_startFlag)
    {
        if (!m_thread->start(*this))
        {
            return false;
        }
        m_startFlag = true;
    }
    Timer* pTimer = const_cast<Timer*>(&timer);
    AutoLock lock(m_tmrlstMutex);
    for(auto tmr : m_timerList)
    {
        if (tmr==pTimer)
        {
            return false;
        }
    }
    pTimer->m_startFlag=false;
    m_timerList.push_back(pTimer);
    return true;
}

bool TimerManager::unregisterTimer(const Timer& timer)
{
    Timer* pTimer = const_cast<Timer*>(&timer);
    AutoLock lock(m_tmrlstMutex);
    for(auto iter=m_timerList.begin();iter!=m_timerList.end();++iter)
    {
        if(*iter == pTimer)
        {
            m_timerList.erase(iter);
            return true;
        }
    }
    return false;
}

void TimerManager::run(Thread& thread)
{
    while(1)
    {
        Thread::msleep(10);
        AutoLock lock(m_tmrlstMutex);
        for(auto tmr : m_timerList)
        {
            tmr->checkAlarm();
        }
    }
}

RTimer::RTimer(const TimerListener& listener,int id):
m_timerID(id)
{
    m_listener = const_cast<TimerListener*>(&listener);
}

RTimer::~RTimer()
{
}

bool RTimer::start(int usTimeout,int usTick,bool repeat)
{
    if (usTimeout<=0 || usTimeout<=usTick || m_timerID<0 || m_listener==nullptr)
    {
        TRACE_ERR_CLASS("Param Error, id:%d, timeout:%d, tick:%d, listener:0x%x",m_timerID,usTimeout,usTick, m_listener);
        return false;
    }
    m_repeat = repeat;
    m_usInterval = usTimeout;
    m_usTick = usTick;
    m_thread = std::make_unique<Thread>();
    return m_thread->start(*this);
}

void RTimer::stop()
{
    if(m_thread)
    {
        if (m_thread->isRunning() && !m_thread->stop(100000))
        {
            m_thread->stop();
        }
        m_thread = nullptr;
    }
}

void RTimer::run(Thread& thread)
{
    bool firstTime=true;
    Time lastTime,currTime;
    while (thread.isRunning()) 
    {
        if (firstTime)
        {
            lastTime = Time::fromMono();
            firstTime = false;
        }
        else
        {
            currTime = Time::fromMono();
            Time timeDiff = currTime-lastTime;
            int usOver = (int)(timeDiff.toMicroSec()) - m_usInterval;
            if(usOver>=0)/* 到了定时时间 */
            {
                //TRACE_DBG("RTimer usOver=%d",usOver);
                if (usOver>m_usInterval)
                {
                    //TRACE_WARN("RTimer over run interval: %d > %d",usOver,m_usInterval);
                    lastTime = currTime;/* 已经超过一个周期了,重新计算差值 */
                }
                else
                {
                    Time overTime(0,usOver);
                    lastTime = currTime-overTime;/* 减去超过的时间 */
                }
                
                if (m_listener!=nullptr)
                {
                    m_listener->onTimer(m_timerID);
                    if (!m_repeat)
                    {
                        break;
                    }
                }
            }
        }
        /* 每隔m_usTick读一次时间 */
        Thread::usleep(m_usTick);
    }
}

EventTimer::EventTimer(int usCheck,int evtMask)
{
    m_timer = std::make_unique<RTimer>(*this,0);
    m_event = RC_ERROR;
    if (m_usCheck<=0)
    {
        m_usCheck = 10000;
    }
    m_usCheck = usCheck;
    m_evtMask = evtMask;
}

EventTimer::~EventTimer()
{
}

void EventTimer::clearEvent()
{
    AutoLock lock(m_cond);
    m_event = RC_ERROR;
}

int EventTimer::waitEvent(std::vector<int> eventList,int usTimeout)
{
    int event;
    if (usTimeout<0)
    {
        /* 阻塞式等待 */
        while(1)
        {
            if(RC_OK==m_cond.wait(m_usCheck) || m_event!=RC_ERROR)
            {
                break;
            }
        }
    }
    else if (usTimeout==0)
    {
        /* 最小必须为一个check周期 */
        usTimeout = m_usCheck;
    }
    else
    {
        if (usTimeout<m_usCheck)
        {
            TRACE_ERR_CLASS("usTimeout set error: %d, should be long than %d",usTimeout,m_usCheck);
            return RC_ERROR;
        }
    }
    {
        AutoLock lock(m_cond);
        m_isStart = true;
        m_eventList = eventList;
        m_isTimeout = false;
        if(!m_timer->start(usTimeout,m_usCheck,false))
        {
            TRACE_ERR_CLASS("cannot start timer!");
            return RC_ERROR;
        }
        bool waited = false;
        while(!m_isTimeout)
        {
            if(RC_OK==m_cond.wait(m_usCheck) || m_event!=RC_ERROR)
            {
                waited = true;
                break;
            }
        }
        if (!waited && m_isTimeout)
        {
            event = RC_TIMEOUT;
        }
        else
        {
            if (event<0)
                event = RC_ERROR;
            else
                event = m_event;
        }
        m_isStart=false;
    }
    m_timer->stop();
    return event;
}

void EventTimer::meetEvent(int event)
{
    AutoLock lock(m_cond);
    if (!m_isStart)
    {
        return;
    }
    for(auto evt: m_eventList)
    {
        if ((event&m_evtMask)==evt)
        {
            m_event = event;
            m_cond.meet();
            break;
        }
    }
}

void EventTimer::onTimer(int timerID)
{
    m_isTimeout = true;
}

}
